#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time        : 2023/10/27 0:41
# @Author      : Mini-Right
# @Email       : www@anyu.wang
# @File        : google.py
# @Software    : PyCharm
# @Description :
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time        : 2023/10/27 0:01
# @Author      : Mini-Right
# @Email       : www@anyu.wang
# @File        : google.py
# @Software    : PyCharm
# @Description :

import json
import time
from datetime import datetime

import requests
from playwright.sync_api import Playwright, sync_playwright
from requests.exceptions import RequestException


class API(object):
    def __init__(self):
        self.session = requests.Session()
        self.base_url = 'http://101.200.166.120:8081'

    def get_to_send_list_api(self):
        """
        获取待发送信息名单
        """
        url = '/autoMsg/getToSendList'
        result = self.invoke(url=url, method='GET')
        print(f"调用[获取待发送信息名单]接口响应: {result}")
        return result['data']

    '''
        调用后端系统获取关键字回复
    '''
    def get_send_msg_api(self, name: str, message_list: list):
        """
        获取关键字回复信息
        """
        url = '/autoMsg/getSendMsg'

        payload = {
            "requestId": int(datetime.now().timestamp() * 1000),
            "requestTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "data": {
                "studentList": [
                    {
                        "name": name,
                        "messages": message_list
                    }
                ]
            }
        }
        print(f"调用[获取关键字回复信息]接口请求: {payload}")
        result = self.invoke(url=url, method='POST', payload=payload)
        print(f"调用[获取关键字回复信息]接口响应: {result}")
        return result['data']

    def invoke(self, url: str, method: str, payload: dict = None):
        response = self.session.request(method=method, url=f"{self.base_url}{url}", json=payload)
        print(response.text)
        if response.status_code == 200 and response.json().get('code') == 200:
            return response.json()
        raise RequestException('接口调用失败')


class InitLarkSuite(object):
    def __init__(self, playwright: Playwright, headless: bool = False):
        self.playwright = playwright
        self.browser = self.playwright.chromium.launch(headless=headless)
        self.context = self.browser.new_context(
            # viewport={'width': 1920, 'height': 1080}
        )
        self.page = self.context.new_page()

        self.cookies_file_path = 'cookies.json'

        self.api = API()

        self.lark_suite_url = 'https://www.feishu.cn/messenger/'

    def save_cookies(self):
        """保存Cookies"""
        cookies = self.page.context.cookies()
        with open(self.cookies_file_path, 'w') as f:
            json.dump(cookies, f)

    def load_cookies(self):
        """加载Cookies"""
        with open(self.cookies_file_path, 'r') as f:
            cookies = json.load(f)
            self.context.add_cookies(cookies)

    def send_message(self, text: str):
        """发送消息"""
        print(f'回复消息: {text}')
        self.page.locator('.lark-editor').fill(text)
        self.page.keyboard.press('Enter')
        self.page.wait_for_timeout(1000 * 1)

    def close(self):
        self.page.close()
        self.context.close()
        self.browser.close()


class LarkSuiteLogin(InitLarkSuite):
    def __init__(self, playwright: Playwright, headless: bool = False):
        super().__init__(playwright=playwright, headless=headless)

    def login(self):
        self.page.goto(self.lark_suite_url)
        self.page.locator('.new-scan-login-box').screenshot(path='./login.png')
        self.page.wait_for_timeout(1000 * 30)

        self.save_cookies()
        self.close()


class LarkSuiteSendMessage(InitLarkSuite):
    def __init__(self, playwright: Playwright, headless: bool = False):
        super().__init__(playwright=playwright, headless=headless)

        to_send_data = self.api.get_to_send_list_api()
        self.send_message_text = to_send_data.get('message')
        self.user_list = to_send_data.get('studentList')
        self.load_cookies()
        self.save_cookies()

    def main(self):
        self.page.goto(self.lark_suite_url)
        self.page.wait_for_timeout(1000 * 3)

        for user in self.user_list:
            self.search_user(user.get('name'))

        print(f"已全部发送完成 请退出")
        time.sleep(60 * 60 * 24)

    def search_user(self, user):
        """搜索用户"""
        print('点击搜索框')
        self.page.locator('.quick-jump-enter-com__box__text-desc').click()

        userName = user.get('name')
        print(f'录入搜索信息: {userName}')
        self.page.locator('.quickJump_input').fill(userName)

        self.page.wait_for_timeout(1000 * 2)
        quick_jump_list = self.page.query_selector_all('.quickJump_resultContainer .jumpItem')
        length = len(quick_jump_list)
        print(f"搜索结果: {length}个")

        name_list = [self.quick_jump_get_name(quick_jump) for quick_jump in quick_jump_list]
        if name_list.count(userName) > 1:
            print(f"[{userName}] 姓名重复 查询到多条 请手动处理")
            with open(f"./duplicate_names.txt", 'a', encoding='utf-8') as f:
                f.write(userName)
            return
        for index, quick_jump in enumerate(quick_jump_list, start=1):
            name = self.quick_jump_get_name(quick_jump)

            name_tag = quick_jump.query_selector('.larkc-tag')
            name_tag_text = name_tag.inner_text().lstrip().rstrip() if name_tag else ''
            if name_tag:
                name = name.replace(name_tag_text, '')
            print(f"[{name}]")
            if name == userName:
                print(f"第{index} / {length}个: {name} = {userName} 符合条件 点击跳转聊天窗口")
                quick_jump.click()
                print('跳出搜索流程')
                self.send_message(user.get('message'))
                return
            print(f"第{index} / {length}个: {name} != {userName} 不符合条件")
        else:
            print(f"未查询到{userName}的结果")
            self.page.locator('.quickJump_box_close').click()

    @staticmethod
    def quick_jump_get_name(quick_jump):
        name = quick_jump.query_selector('.jumpItem_name').inner_text().lstrip().rstrip().replace('\n', '')
        return name

    def get_last_message(self):
        """获取聊天记录"""
        self.page.wait_for_timeout(1000 * 2)
        message_list = self.page.query_selector_all('.chatMessages .list_items .message-last')
        last_message = message_list[len(message_list) - 1]
        last_message_text = last_message.inner_text()
        is_not_self = last_message.query_selector('.message-not-self')
        print(f"最后一条消息发送人: {'对方' if is_not_self else '自己'}")
        if is_not_self:
            print(f"对方最后一条消息: {last_message_text}")
        return last_message_text


class LarkSuiteNotRead(InitLarkSuite):
    def __init__(self, playwright: Playwright, headless: bool = False):
        super().__init__(playwright=playwright, headless=headless)
        self.load_cookies()
        self.save_cookies()
        # 操作计数 每100次刷新下页面
        self.count = 0
        self.index = 0
        self.user_map = {}

    def main(self):
        self.page.goto(self.lark_suite_url)
        self.page.wait_for_timeout(1000 * 5)
        while True:
            try:
                self.not_read_send_message()
                self.scroll_up()
                self.page.wait_for_timeout(1000 * 1)
                self.index += 1
                self.count += 1
                if self.count >= 100:
                    self.refresh_and_reset_index()
            except Exception as e:
                print(e)
                self.refresh_and_reset_index()

    def refresh_and_reset_index(self):
        self.reload()
        self.index = 0

    def not_read_send_message(self):
        """未读消息发送"""
        item_list = self.page.query_selector_all('div[role="listitem"]')

        if not item_list:
            print('消息列表为空')
            raise

        item_list_length = len(item_list)
        if self.index >= item_list_length:
            self.index = -1
            return

        item = item_list[1 if self.index == 2 else 0] if item_list_length != 2 else item_list[self.index]

        data_feed_id = item.get_attribute('data-feed-id')

        # 名称
        username = item.query_selector('.feedCardName-text').inner_text()
        print(username)
        if data_feed_id not in self.user_map:
            self.user_map[data_feed_id] = {
                'message': None,
                'is_read': None,
                'is_group': None,
            }
        # if self.user_map[data_feed_id]['is_group']:
        #     return self.done(item, item_list_length, data_feed_id)

        if '机器人' in item.text_content():
            return self.done(item, item_list_length, data_feed_id)

        # 未读消息
        feed_card_has_new = item.query_selector('.feedCard_hasNew')
        # 已/未读 icon
        feed_message_preview_tag = item.query_selector('div[class="larkc-badge-count circle larkc-badge-normal"]')

        # 聊天窗口打开
        if item_list_length >= 2 or (feed_card_has_new or not feed_message_preview_tag):
            item.click()
            self.page.wait_for_timeout(1000 * 3)

        if self.page.query_selector('.chatWindow_count'):
            print(f"{username} 群聊 跳过")
            self.user_map[data_feed_id]['is_group'] = True
            self.done(item, item_list_length, data_feed_id)
            return

        # 未读消息列表
        not_self_message_list = self.get_not_self_message()
        if not not_self_message_list:
            return self.done(item, item_list_length, data_feed_id)
        if self.user_map[data_feed_id]['message'] == not_self_message_list[0]:
            print(f"已回复")
            return self.done(item, item_list_length, data_feed_id)
        self.user_map[data_feed_id]['message'] = not_self_message_list[-1]

        # 消息回复
        reply_list = self.get_reply(username, not_self_message_list)
        for reply in reply_list:
            self.send_message(reply)

        self.done(item, item_list_length, data_feed_id)

        return

    def done(self, item, item_list_length, data_feed_id):
        if item_list_length <= 2:
            return
        item.hover()
        self.page.wait_for_timeout(1000 * 0.5)
        item.query_selector('.feedCardDoneButton').click()
        del self.user_map[data_feed_id]

    def get_not_self_message(self):
        """获取未读聊天记录"""

        not_self_message_list = []

        message_list = self.page.query_selector_all('.chatMessages .message-section')
        for message in message_list[::-1]:
            message_text = message.inner_text()
            is_self = message.query_selector('.read-status-bar')
            if is_self:
                print(f"我说: {message_text}")
                break
            else:
                print(f"对方说: {message_text}")
                not_self_message_list.append(message_text)

        return not_self_message_list

    def get_reply(self, name: str, message_list: list):
        """
        获取回复
        """
        result = self.api.get_send_msg_api(name, message_list)
        if not result:
            return
        reply_list = result.get('studentList')[0].get('answers') if result.get('studentList') else []
        return reply_list if reply_list else []

    def scroll_down(self):
        self.page.evaluate(
            'var div = document.getElementsByClassName("scroller")[0];div.scrollTop = div.scrollHeight'
        )
        self.page.wait_for_timeout(1000 * 1)

    def scroll_up(self):
        self.page.evaluate(
            'var div = document.getElementsByClassName("scroller")[0];div.scrollTop = 0'
        )
        self.page.wait_for_timeout(1000 * 1)

    def reload(self):
        print(f"刷新页面")
        self.page.reload()
        self.count = 0
        self.page.wait_for_timeout(1000 * 5)


if __name__ == '__main__':
    try:
        operate_type = input(f"[1] 登录\n[2] 批量回复\n[3] 未读回复\n请输入序号选择操作： ")
        with sync_playwright() as playwright:
            if operate_type == '1':
                LarkSuiteLogin(playwright, False).login()
            elif operate_type == '2':
                LarkSuiteSendMessage(playwright, False).main()
            elif operate_type == '3':
                LarkSuiteNotRead(playwright, False).main()
    except Exception as e:
        print(e)
        time.sleep(60 * 60 * 1)
